#ifndef FONT_UTILS
#define FONT_UTILS 1

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>

/* clang-format off */

typedef struct {
  uint32_t bitmap_index : 20;     /**< Start index of the bitmap. A font can be max 1 MB.*/
  uint32_t adv_w : 12;            /**< Draw the next glyph after this width. 8.4 format (real_value * 16 is stored).*/
  uint8_t box_w;                  /**< Width of the glyph's bounding box*/
  uint8_t box_h;                  /**< Height of the glyph's bounding box*/
  int8_t ofs_x;                   /**< x offset of the bounding box*/
  int8_t ofs_y;                   /**< y offset of the bounding box. Measured from the top of the line*/
} lv_font_fmt_txt_glyph_dsc_t;

typedef uint8_t lv_font_fmt_txt_cmap_type_t;

enum {
  LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY
};

/**
 * Map codepoints to a `glyph_dsc`s
 * Several formats are supported to optimize memory usage
 * See https://github.com/lvgl/lv_font_conv/blob/master/doc/font_spec.md
 */
typedef struct {
  /** First Unicode character for this range*/
  uint32_t range_start;

  /** Number of Unicode characters related to this range.
    * Last Unicode character = range_start + range_length - 1*/
  uint16_t range_length;

  /** First glyph ID (array index of `glyph_dsc`) for this range*/
  uint16_t glyph_id_start;

  /*
  According the specification there are 4 formats:
      https://github.com/lvgl/lv_font_conv/blob/master/doc/font_spec.md

  For simplicity introduce "relative code point":
      rcp = codepoint - range_start

  and a search function:
      search a "value" in an "array" and returns the index of "value".

  Format 0 tiny
      unicode_list == NULL && glyph_id_ofs_list == NULL
      glyph_id = glyph_id_start + rcp

  Format 0 full
      unicode_list == NULL && glyph_id_ofs_list != NULL
      glyph_id = glyph_id_start + glyph_id_ofs_list[rcp]

  Sparse tiny
      unicode_list != NULL && glyph_id_ofs_list == NULL
      glyph_id = glyph_id_start + search(unicode_list, rcp)

  Sparse full
      unicode_list != NULL && glyph_id_ofs_list != NULL
      glyph_id = glyph_id_start + glyph_id_ofs_list[search(unicode_list, rcp)]
  */

  const uint16_t * unicode_list;

  /** if(type == LV_FONT_FMT_TXT_CMAP_FORMAT0_...) it's `uint8_t *`
    * if(type == LV_FONT_FMT_TXT_CMAP_SPARSE_...)  it's `uint16_t *`
    */
  const void * glyph_id_ofs_list;

  /** Length of `unicode_list` and/or `glyph_id_ofs_list`*/
  uint16_t list_length;

  /** Type of this character map*/
  lv_font_fmt_txt_cmap_type_t type;
} lv_font_fmt_txt_cmap_t;

/*Describe store additional data for fonts*/
typedef struct {
  /*The bitmaps of all glyphs*/
  const uint8_t * glyph_bitmap;

  /*Describe the glyphs*/
  const lv_font_fmt_txt_glyph_dsc_t * glyph_dsc;

  /*Map the glyphs to Unicode characters.
    *Array of `lv_font_cmap_fmt_txt_t` variables*/
  const lv_font_fmt_txt_cmap_t * cmaps;

  /**
    * Store kerning values.
    * Can be `lv_font_fmt_txt_kern_pair_t *  or `lv_font_kern_classes_fmt_txt_t *`
    * depending on `kern_classes`
    */
  const void * kern_dsc;

  /*Scale kern values in 12.4 format*/
  uint16_t kern_scale;

  /*Number of cmap tables*/
  uint16_t cmap_num       : 9;

  /*Bit per pixel: 1, 2, 3, 4, 8*/
  uint16_t bpp            : 4;

  /*Type of `kern_dsc`*/
  uint16_t kern_classes   : 1;

  /*
    * storage format of the bitmap
    * from `lv_font_fmt_txt_bitmap_format_t`
    */
  uint16_t bitmap_format  : 2;
} lv_font_fmt_txt_dsc_t;

typedef struct {
  uint32_t glyph_bitmap_size;
  uint8_t line_height;
  uint8_t base_line;
  const lv_font_fmt_txt_dsc_t *dsc;
} modify_lv_font_t ;

/* clang-format on */

void print_font(uint8_t x, uint8_t y, const char *str);
extern void setPixel(uint8_t x, uint8_t y, bool value);

extern const modify_lv_font_t firacode_light9;
extern const modify_lv_font_t firacode_light12;
extern const modify_lv_font_t firacode_light14;
extern const modify_lv_font_t firacode_light16;

extern const modify_lv_font_t zpix12;
extern const modify_lv_font_t zpix12_cn;
#endif /*#if FONT_UTILS*/